/**
**************************************************************************************
*Founder Effect                                                                      *
*Copyright (C) 2006-2007, 5d Studios (www.5d-Studios.com)                            *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/
#pragma once
#pragma warning( disable : 4244)

#include "../shared/geom.h"

#include <deque>


/**
=========================
A movable camera
=========================
*/
class ICamera
{
public:

    ICamera() : m_active(true), m_mainCamera(false), m_id( CAMERA_ID++ ),
        m_friction(0.0f) {}

    /** Initialize the camera */
    virtual bool Init()=0;
    /** Update the camera to another location if needed */
	virtual void Update(float dt)=0;

    /** Point the camera at a location */
    virtual void LookAt( const MVector3f &pos )=0;
    /** Move the Camera over time to this new location, multiplied by the speed var */
    virtual void MoveTo( const MVector3f &dest ) =0;
    /** Shake the camera for a duration and a velocity */
    virtual void Shake( float time, float magnitude )=0;

    /** Test to see if this rectangle intersects with the viewport */
    virtual bool Contains( const MAABBox3f &r  )=0; 
    /** Test to see if this point intersects with the viewport */
    virtual bool Contains( const MVector3f &v )=0;

    /** Set a path for the camera to follow */
    void SetPath( std::deque<MVector3f> pathToFollow ) { m_pathToFollow = pathToFollow; };
    /** Add to path */
    void AddToPath( const MVector3f &v ) { m_pathToFollow.push_front( v ); };

    /** Get the Position of the camera (world relative) */
    virtual MMatrix4x4f GetProjectionMat() const=0; 
    /** Sets the new position, also recalculates the viewport properly */
    virtual void SetProjectionMat( const MMatrix4x4f &m )=0; 

    /** Set the up vector */
    virtual void SetUpVector( const MVector3f &v ) =0;
    virtual MVector3f GetUpVector() const=0;

    /** Set the FOV */
    virtual void SetFOV ( float f )=0;
    virtual float GetFOV() const=0;

    /** Set the aspect ration */
    virtual void SetAspectRatio( float f )=0;
    virtual float GetAspectRation() const=0;

    /** Set the dimensions of the camera */
    virtual void SetFrustum(const MFrustum &f )=0;
    virtual const MFrustum* GetFrustum() const =0;

    /** Activate/ Deactivate this camera */
    bool IsActivated() const { return m_active; };
    void Activate( bool b ) { m_active = b; };

    /** Set the speed of the camera motion */
    MVector3f   GetVelocity() const { return m_baseVel; };
    void        SetVelocity( const MVector3f &vel ) { m_baseVel = vel; };
    
    /** Set the friction */
    float GetFriction() const { return m_friction; };
    void  SetFriction(float f) { m_friction = f; };

    /** Retreive this cams id */
    int GetID() const { return m_id; };

    /** Test to see if this is the main camera */
    bool IsMainCamera() const { return m_mainCamera; };

    /** Set to be the main camera */
    virtual void SetMainCamera()=0;

    virtual ~ICamera() {};

protected:
    bool                m_active;
    bool                m_mainCamera;
    unsigned int        m_id;
    

    MVector3f       m_dest;
    MVector3f       m_velocity;
    MVector3f       m_baseVel;
    MVector3f       m_oldBaseVel;   // base vel if just moving w/o latched entity
    float           m_friction;

    /** Path to follow - Takes presedence vs AttachedTo */
    typedef std::deque<MVector3f> type_Vectors;
    type_Vectors m_pathToFollow;

    /** Camera ID */
    static unsigned int CAMERA_ID;
};

   ///** Get the Position of the camera (world relative) */
   // MMatrix4x4f GetProjectionMat() { return m_projection; };
   // /** Sets the new position, also recalculates the viewport properly */
   // void SetProjectionMat( const MMatrix4v4f &m ) {     
   //     m_projection = m; 
   // };

   // /** Set the up vector */
   // void SetUpVector( const MVector3f &v ) { m_up = v; };
   // MVector3f GetUpVector() const { return m_up; };

   // /** Set the FOV */
   // void SetFOV ( float f ) { m_FOV = f; };
   // float GetFOV() const { return m_FOV; };

   // /** Set the aspect ration */
   // void SetAspectRatio( float f ) { m_aspectRatio = f; };
   // float GetAspectRation() const { return m_aspectRatio; };

   // /** Set the dimensions of the camera */
   // void SetFrustum(const MFrustum &f ) { m_frustum = f; };
   // MFrustum GetFrustum() const { return m_frustum; };